
#include "Hal_Remote/Hal_remote.h"
#include "delay.h"
#include "stm32f10x_rcc.h"
#include "stm32f10x_gpio.h"
#include "stm32f10x_exti.h"
#include "stm32f10x_tim.h"
#include "misc.h"
#include "Hal_Usart/hal_uart.h"
#include "gizwits_product.h"

unsigned char  irtime=0;//红外用全局变量
unsigned char IRcord[4];
unsigned char irdata[33];
u8 irpro_ok,irok;
u8 irctl=0;
//中断优先级管理/开启	   
void NVIC_Configuration_RED(void)
{
	NVIC_InitTypeDef NVIC_InitStructure;
	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);  //采用组别2	 
 
	NVIC_InitStructure.NVIC_IRQChannel = EXTI3_IRQn;//配置外部中断1
	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;//占先式优先级设置为0
	NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0; //副优先级设置为0
	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;//中断使能
  NVIC_Init(&NVIC_InitStructure); 								 
}

//红外接收，外部中断初始化函数PC13
void EXTI_Init_Remote(void)
{	
	//对GPIO操作一定要先使能对应时钟
	GPIO_InitTypeDef GPIO_InitStructure;  //定义GPIO结构体	
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);//使能GPIOA、GPIOB口时钟
//	GPIO_PinRemapConfig(GPIO_Remap_SWJ_JTAGDisable , ENABLE);
	/*将PB0,PB1配置为推挽输出*/
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3;//PA11
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;	//上拉输入
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;	//50M时钟速度
	GPIO_Init(GPIOB, &GPIO_InitStructure);
	
	

} 
void EXTI_Config(void){
	EXTI_InitTypeDef EXTI_InitStructure;
	EXTI_ClearITPendingBit(EXTI_Line3);	//清除1线标志位
	EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;
	EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Falling;	//边沿触发
	EXTI_InitStructure.EXTI_Line = EXTI_Line3;
	EXTI_InitStructure.EXTI_LineCmd = ENABLE;
	EXTI_Init(&EXTI_InitStructure);	 //根据以上参数初始化结构体
	GPIO_EXTILineConfig(GPIO_PortSourceGPIOB,GPIO_PinSource3);	//PA1作为外部中断线1引脚
}
void timer4Init(void)
{
    u16 arr = 250;//250us
    u16 psc = 71;
    TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure;
    NVIC_InitTypeDef NVIC_InitStructure;

    RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM4, ENABLE); //时钟使能

    //定时器TIM3初始化
    TIM_TimeBaseStructure.TIM_Period = arr; //设置在下一个更新事件装入活动的自动重载寄存器周期的值
    TIM_TimeBaseStructure.TIM_Prescaler =psc; //设置用来作为TIMx时钟频率的预分频值
    TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1; //设置时钟分割:TDTS = Tck_tim
    TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;  //TIM向上计数模式
    TIM_TimeBaseInit(TIM4, &TIM_TimeBaseStructure); //根据指定的参数初始化TIMx的时间基数单位0

    TIM_ITConfig(TIM4, TIM_IT_Update,ENABLE ); //使能指定的TIM3中断,允许更新中断

    //中断优先级NVIC设置
    NVIC_InitStructure.NVIC_IRQChannel = TIM4_IRQn;  //TIM3中断
    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;  //优占优先级0级
    NVIC_InitStructure.NVIC_IRQChannelSubPriority = 2;  //从优先级3级
    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //IRQ通道被使能
    NVIC_Init(&NVIC_InitStructure);  //初始化NVIC寄存器
    TIM_Cmd(TIM4, DISABLE);  //使能TIMx
}
/**
* @brief 定时器TIM3中断处理函数

* @param none
* @return none
*/
void TIM4_IRQHandler(void)
{
    if (TIM_GetITStatus(TIM4, TIM_IT_Update) != RESET)  
    {
        TIM_ClearITPendingBit(TIM4, TIM_IT_Update  );
        irtime++;  //用于计数2个下降沿之间的时间
//			printf("irtime:%d\r\n",irtime);
    }
}
//u8 check(void)
//{
//    u8 t=0;
//    while(GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_3)==1)
//    {
//        t++;
//        delayUs(20);
//        if(t==250)return t; //超时溢出
//    }
//    return t;
//}      

/*-------------------------协议--------------------------
开始拉低9ms,接着是一个4.5ms的高脉冲,通知器件开始传送数据了
接着是26位前导脉冲,用于识别该型号的摇控。
然后是发送8位数据的原码，接着又发送8位数据的反码.
最后是一个长脉冲，和开始位一样，拉低9ms和一个4.5ms脉冲表示结束。
每个按键不同这处只在于那8位数据的原码和反码，因些只须要识别
8位原码就可以识别按键了
---------------------------------------------------------*/

/********************************************************* 
                中断服务程序 
********************************************************/  
void EXTI3_IRQHandler()       
{  

	static unsigned char  i;             //接收红外信号处理
	static u8 startflag;                //是否开始处理标志位
     if(EXTI_GetITStatus(EXTI_Line3) == SET)//检查指定的EXTI线路触发请求发生与否，返回一个EXTI_Line新状态  
      {  
				 if(EXTI_GetITStatus(EXTI_Line3) == SET)//检查指定的EXTI线路触发请求发生与否，返回一个EXTI_Line新状态  
      {  
            //GIZWITS_LOG("5\r\n");   
			
						if(startflag)                         
						{
						
						if(irtime<63&&irtime>=33)//引导码 TC9012的头码，9ms+4.5ms
							i=0;

						irdata[i]=irtime;//存储每个电平的持续时间，用于以后判断是0还是1
						//printf("irdata[%d]:%d\r\n",i,irdata[i]);
						
						irtime=0;
						i++;
						//GIZWITS_LOG("6\r\n");   
						if(i==33)
							{
							irok=1;
							i=0;
							TIM_Cmd(TIM4,DISABLE);
								//	GIZWITS_LOG("7\r\n"); 
							}
//							if(i<33)
//								TIM_Cmd(TIM4,ENABLE);
//							GIZWITS_LOG("7\r\n");  
						if((i>=22)&&(i<=28))
						{
							irctl=1;
							i=0;
						
						GIZWITS_LOG("7\r\n"); 
						}
						}
						else
						{
						TIM_Cmd(TIM4,ENABLE);
						irtime=0;
						startflag=1;
						GIZWITS_LOG("8\r\n");   
						}  
            EXTI_ClearITPendingBit(EXTI_Line3);//清除线路挂起位  
            EXTI_ClearFlag(EXTI_Line3);//清除中断挂起位   
					
     }   
	 }
			}  
/*------------------------------------------------
                  键值处理
------------------------------------------------*/

void Ir_work(void)//红外键值散转程序
{
       switch(IRcord[2])//判断第三个数码值
	         {
			 case 0x0c:printf("1\r\n");break;//1 显示相应的按键值
			 case 0x18:printf("2\r\n");break;//2
			 case 0x5e:printf("3\r\n");break;//3
			 case 0x08:printf("4\r\n");break;//4
			 case 0x1c:printf("5\r\n");break;//5
			 case 0x5a:printf("6\r\n");break;//6
			 case 0x42:printf("7\r\n");break;//7
			 case 0x52:printf("8\r\n");break;//8
			 case 0x4a:printf("9\r\n");break;//9
             default:break;
			 }

		  irpro_ok=0;//处理完成标志

}

 
/*------------------------------------------------
                红外码值处理
------------------------------------------------*/
void Ircordpro(void)//红外码值处理函数
{ 
  unsigned char i, j, k;
  unsigned char cord,value;
	printf("Come in to Ircordpro\r\n");
  k=1;
  for(i=0;i<4;i++)      //处理4个字节
     {
      for(j=1;j<=8;j++) //处理1个字节8位
         {
          cord=irdata[k];
          if(cord>7)//大于某值为1，这个和晶振有绝对关系，这里使用12M计算，此值可以有一定误差
             value|=0x80;
          if(j<8)
		    {
			 value>>=1;
			}
           k++;
         }
     IRcord[i]=value;
     value=0;     
     } 
	 irpro_ok=1;//处理完毕标志位置1
}
////-----------------------------------------------------------------------------------------------------------------




void RedInit(void)
{	
	timer4Init();
	EXTI_Init_Remote();//初始化外部中断
	EXTI_Config();
	NVIC_Configuration_RED();
	GIZWITS_LOG("Init Timer 4\r\n");
}

////-----------------------------------------------------------------------------------------------------------------


void redRead(void)
{
    if(irok)                        //如果接收好了进行红外处理
	  {   
	   Ircordpro();
 	   irok=0;
	  }
    if(irpro_ok)                   //如果处理好后进行工作处理，如按对应的按键后显示对应的数字等
	  	   	 Ir_work();
}


